package com.atguigu.yygh.cmn.service.impl;

import com.alibaba.excel.EasyExcel;
import com.atguigu.yygh.cmn.listener.DictListener;
import com.atguigu.yygh.cmn.mapper.DictMapper;
import com.atguigu.yygh.cmn.service.DictService;
import com.atguigu.yygh.model.cmn.Dict;
import com.atguigu.yygh.model.hosp.Hospital;
import com.atguigu.yygh.vo.cmn.DictEeVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * @description: 根据数据id查询子数据列表，判断id下面是否有子节点
 * 把list集合遍历，得到里面的每个对象的ID，
 * 调用isChildren方法传入对象ID，判断HasChildren属性是否为True
 * 再将True或者False赋值给dict对象的HasChildren属性【此属性是前端的页面展示数据字典需要】
 * @author: 化一帆
 * @date: 2022/11/23 18:49
 * @version: v1.0
 */
@Service
public class DiceServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
  //ServiceImpl中注入了BaseMapper
   /* @Autowired
    private DictMapper dictMapper;*/
    //实现类
  @Autowired
  DictListener dictListener;
  /**
   * @description:根据数据id查询子数据列表【传id查询它下面的子数据，返回True或者false，并且设置属性hasChildren】
   * @author 化一帆
   * @date 2022/11/24 10:49
   */
    @Override
    @Cacheable(value = "dict",keyGenerator = "keyGenerator")//执行之前先判断缓存中是否存在数据
    public List<Dict> findChildData(Long id) {
        QueryWrapper<Dict> Wrapper = new QueryWrapper<>();
        Wrapper.eq("parent_id", id);
        List<Dict> dictList = baseMapper.selectList(Wrapper);

        //向list集合中每个dict对象中设置hasChildren[这个值要么为True，要么为False]
        for(Dict dict:dictList){
            //调用二级标题的id，判断二级标题下是否还有三级标题
            Long dictId = dict.getId();
            boolean isChild = this.isChildren(dictId);
            dict.setHasChildren(isChild);
        }
        //此时再返回dict对象的HasChildren属性就有了值
        return dictList;
    }


    /**
     * @description:判断id下面是否有子节点
     * @author 化一帆
     * @date 2022/11/24 10:48
     */
    private boolean isChildren(Long id){
        QueryWrapper<Dict> Wrapper = new QueryWrapper<>();
        Wrapper.eq("parent_id", id);
        Integer count = baseMapper.selectCount(Wrapper);
        //0>0 False  1>0 True
        return count>0;
    }

    /**
     * @description:导出数据字典
     * @author 化一帆
     * @date 2022/11/24 10:49
     */
    @Override
    public void exportDictData(HttpServletResponse response) {
        //1、设置响应头，设置下载的信息
        response.setContentType("application/vnd.ms-excel"); //指示响应内容的格式
        response.setCharacterEncoding("utf-8");//字符集
        String fileName = "dict";
        response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");//附件形式下载

        //查询数据库
        List<Dict> dictList = baseMapper.selectList(null);

        //将数据库的对象遍历。将属性赋值转换为DictEeVo对象,dictEeVo.setId(dict.getId())
        //vo对象用于与表格的orm映射，在属性上加注解
        ArrayList<DictEeVo> dictVoList = new ArrayList<>();
        for(Dict dict:dictList){
            DictEeVo dictEeVo = new DictEeVo();
            //将dict中的内容复制到dictEeVo中
            BeanUtils.copyProperties(dict, dictEeVo);
            dictVoList.add(dictEeVo);
        }

        //调用方法进行写的操作【参数1 响应流    参数2 ORM映射】
        try {
            EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("dict")//指定Sheet表的名字，默认为0
                    //此处的list里面的对象应该是DictEeVo
                    .doWrite(dictVoList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @description:导入数据字典
     * @author 化一帆
     * @date 2022/11/24 14:38
     */
    @Override
    @CacheEvict(value = "dict", allEntries=true)//做一个添加操作或者修改的操作，数据库中的内容会发生变化，此时需要清空缓存，重新进行缓存
    public void importDictData(MultipartFile file) {
        //第一个参数是文件的流，文件输入流
        //第二个参数参数是文件的class
        //第三个参数New监听器
        try {
            EasyExcel.read(file.getInputStream(),DictEeVo.class,dictListener).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @description: 查询数据字典的名称
     * @author 化一帆
     * @date 2022/11/29 14:35
     */

    @Override
    public String getDictName(String dictCode, String value) {

        if(StringUtils.isEmpty(dictCode)){
            //如果dictCode为空，直接根据value进行查询
            QueryWrapper<Dict> wrapper = new QueryWrapper<>();
            wrapper.eq("value", value);
            Dict dict = baseMapper.selectOne(wrapper);
            return dict.getName();
        }else{
            //如果dictCode不为空，根据dictCode和value进行查询
            //TODO dictCode不对应数据，只对应分类[拥有dictCode的都是上级]
            //TODO 首先根据dictCode查出id值【父节点】，再根据id值查出它的子节点parent_id


            //根据dictCode查询dict上级对象，得到dict的id值,对应为parent_id
            QueryWrapper<Dict> wrapper = new QueryWrapper<>();
            wrapper.eq("dict_code", dictCode);
            Dict highDict = baseMapper.selectOne(wrapper);
            Long id = highDict.getId();


            //根据id值和value值进行查询
            QueryWrapper<Dict> Wrapper2 = new QueryWrapper<>();
            Wrapper2.eq("parent_id", id)
                    .eq("value", value);
            Dict dict = baseMapper.selectOne(Wrapper2);
            return  dict.getName();
        }
    }

    /**
     * @description: 根据dictCode获取下级节点
     * @author 化一帆
     * @date 2022/11/29 16:50
     */
    @Override
    public List<Dict> findByDictCode(String dictCode) {
        //根据dictCode获取对应的id
        QueryWrapper<Dict> dictQueryWrapper = new QueryWrapper<>();
        dictQueryWrapper.eq("dict_code", dictCode);
        Dict dict = baseMapper.selectOne(dictQueryWrapper);
        //根据id获取子节点
        List<Dict> childData = this.findChildData(dict.getId());
        return childData;

    }
}
